package best.driver.android.common.push;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import best.driver.android.common.account.AccountManagerListener;
import best.driver.android.common.account.IAccount;
import best.driver.android.manager.CustomerManager;

public abstract class AbstractPushMessageManager implements IPushMessageManager {

    private enum DeviceState {
        WaitingUpload(0),//待上传
        Uploaded(1),//已上传
        Binded(2),//已绑定
        Unbinded(3);//解除绑定

        private int value;

        DeviceState(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public static DeviceState valueOf(int value) {
            if (value == 0) return WaitingUpload;
            if (value == 1) return Uploaded;
            if (value == 2) return Binded;
            if (value == 3) return Unbinded;

            return WaitingUpload;
        }
    }

    private static final String TAG = "PushMessageManager";
    private static final String PUSH_CACHE_PREFERENCE_NAME = "push_cache";
    private static final String PUSH_CACHE_KEY_DEVICE_ID = "device_id";
    private static final String PUSH_CACHE_KEY_STATE = "state";

    private Context mContext;
    private String mDeviceId;
    private DeviceState mDeviceState = DeviceState.WaitingUpload;

    public AbstractPushMessageManager(Context context) {
        mContext = context;

        init();
    }

    public void setDeviceToken(String token) {
        Log.d(TAG, "setDeviceToken:" + token);

        if (mDeviceId == null || !mDeviceId.equalsIgnoreCase(token)) {
            mDeviceId = token;
            mDeviceState = DeviceState.WaitingUpload;
            cacheDeviceId(token);
            updateTokenState();
        }
    }

    @Override
    public String getDeviceToken() {
        return mDeviceId;
    }

    @Override
    public abstract IPushDeviceTokenBinder getDeviceTokenBinder();

    @Override
    public abstract IPushMessageHandler getPushMessageHandler();

    public DeviceState getDeviceState() {
        return mDeviceState;
    }

    public void setDeviceState(DeviceState deviceState) {
        if (mDeviceState != deviceState) {
            mDeviceState = deviceState;
            cacheDeviceState();
        }
    }

    protected abstract void onInit();

    private void init() {
        getDeviceTokenBinder().setListener(new PushDeviceTokenBinderListenerImpl());
        CustomerManager.instance().addListener(new AccountManagerListenerImpl());

        mDeviceId = loadCachedDeviceId();
        mDeviceState = loadCachedDeviceState();

        Log.d(TAG, "init,deviceId:" + mDeviceId + ",state:" + mDeviceState);

        onInit();

        if (mDeviceId != null) {
            updateTokenState();
        }
    }

    private void updateTokenState() {
        Log.d(TAG, "updateTokenState");

        boolean isAccountLogin = CustomerManager.instance().isCustomerLogin();
        if (getDeviceToken() != null && isAccountLogin && getDeviceState() != DeviceState.Binded) {
            Log.d(TAG, "uploadDeviceToken");
            getDeviceTokenBinder().cancelProcess();
            getDeviceTokenBinder().uploadDeviceToken(getDeviceToken());
        } else if (getDeviceToken() != null && !isAccountLogin && getDeviceState() == DeviceState.Binded) {
            Log.d(TAG, "unbindDeviceToken");
            getDeviceTokenBinder().cancelProcess();
            getDeviceTokenBinder().unbindDeviceToken(getDeviceToken());
        } else if (getDeviceToken() != null && !isAccountLogin && getDeviceState() == DeviceState.WaitingUpload) {
            Log.d(TAG, "uploadDeviceToken");
            getDeviceTokenBinder().cancelProcess();
            getDeviceTokenBinder().uploadDeviceToken(getDeviceToken());
        }
    }

    private void cacheDeviceId(String deviceId) {
        SharedPreferences sp = mContext.getSharedPreferences(PUSH_CACHE_PREFERENCE_NAME, Context.MODE_PRIVATE);
        sp.edit().putString(PUSH_CACHE_KEY_DEVICE_ID, deviceId).commit();
    }

    private String loadCachedDeviceId() {
        SharedPreferences sp = mContext.getSharedPreferences(PUSH_CACHE_PREFERENCE_NAME, Context.MODE_PRIVATE);
        return sp.getString(PUSH_CACHE_KEY_DEVICE_ID, null);
    }

    private void cacheDeviceState() {
        SharedPreferences sp = mContext.getSharedPreferences(PUSH_CACHE_PREFERENCE_NAME, Context.MODE_PRIVATE);
        sp.edit().putInt(PUSH_CACHE_KEY_STATE, mDeviceState.getValue()).commit();
    }

    private DeviceState loadCachedDeviceState() {
        SharedPreferences sp = mContext.getSharedPreferences(PUSH_CACHE_PREFERENCE_NAME, Context.MODE_PRIVATE);
        int value = sp.getInt(PUSH_CACHE_KEY_STATE, DeviceState.WaitingUpload.getValue());
        return DeviceState.valueOf(value);
    }

    private class PushDeviceTokenBinderListenerImpl implements PushDeviceTokenBinderListener {

        @Override
        public void onUploadDeviceTokenSuccess() {
            if (CustomerManager.instance().isCustomerLogin()) {
                Log.d(TAG, "onUploadDeviceTokenSuccess,binded");
                setDeviceState(DeviceState.Binded);
            } else {
                Log.d(TAG, "onUploadDeviceTokenSuccess,Uploaded");
                setDeviceState(DeviceState.Uploaded);
            }
        }

        @Override
        public void onUploadDeviceTokenFailed(Exception error) {

        }

        @Override
        public void onUnbindDeviceTokenSuccess() {
            Log.d(TAG, "onUnbindDeviceTokenSuccess");
            setDeviceState(DeviceState.Unbinded);
        }

        @Override
        public void onUnbindDeviceTokenFailed(Exception error) {

        }
    }

    private class AccountManagerListenerImpl implements AccountManagerListener {

        @Override
        public void onAccountDidLogin(IAccount account) {
            if (getDeviceToken() != null) {
                Log.d(TAG, "onAccountDidLogin uploadDevice");
                getDeviceTokenBinder().cancelProcess();
                getDeviceTokenBinder().uploadDeviceToken(getDeviceToken());
            }
        }

        @Override
        public void onAccountDidLogout() {
            if (getDeviceToken() != null) {
                Log.d(TAG, "onAccountDidLogout unbindDevice");
                getDeviceTokenBinder().cancelProcess();
                getDeviceTokenBinder().unbindDeviceToken(getDeviceToken());
            }
        }

        @Override
        public void onAccountProfileUpdate(IAccount account) {

        }

		@Override
		public void onNotifyIdentyChange() {
			
		}

		@Override
		public void onTokenExpired() {
			
		}

        @Override
        public void onCheckStatusChange() {

        }
    }

    //todo 前后台切换,重新检查上传

}
